package com.ltxtiyu.video.service;

import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.ltxtiyu.video.bean.MessageInfoBean;
import com.ltxtiyu.video.bean.VideoInfoBean;
import com.ltxtiyu.video.cacheDao.ConfigCacheDao;
import com.ltxtiyu.video.cacheDao.MomentCacheDao;
import com.ltxtiyu.video.cacheDao.UserCacheDao;
import com.ltxtiyu.video.cacheDao.VideoCacheDao;
import com.ltxtiyu.video.common.CodeTypeConstant;
import com.ltxtiyu.video.common.ConfigConstant;
import com.ltxtiyu.video.common.JsonTool;
import com.ltxtiyu.video.common.RetEnum;
import com.ltxtiyu.video.dao.ltx.*;
import com.ltxtiyu.video.entity.*;
import com.ltxtiyu.video.service.app.MomentService;
import com.ltxtiyu.video.tool.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.transaction.annotation.Transactional;

import javax.sound.sampled.Line;
import java.util.*;

/**
 * 相关moment的业务实现
 */
@Service
public class MomentServiceImpl implements MomentService {
    private final static Logger LOGGER = LoggerFactory.getLogger(MomentServiceImpl.class);
    @Autowired
    StringRedisTemplate stringRedisTemplate;
    @Autowired
    private AmqpTemplate amqpTemplate;

    @Autowired
    UserCacheDao userCacheDao;
    @Autowired
    AreaDao areaDao;
    @Autowired
    ConfigCacheDao configCacheDao;
    @Autowired
    UserFollowDao userFollowDao;
    @Autowired
    MomentDao momentDao;
    @Autowired
    MomentCountDao momentCountDao;
    @Autowired
    VideoCacheDao videoCacheDao;
    @Autowired
    MomentCacheDao momentCacheDao;
    @Autowired
    CommentDao commentDao;
    @Autowired
    MomentLikeDao momentLikeDao;
    @Autowired
    TopicDao topicDao;
    @Autowired
    MomentRemindDao momentRemindDao;
    @Autowired
    MessageDao messageDao;
    @Autowired
    VideoDao videoDao;


    /**
     * 查询个人动态列表
     * @param params
     * @return
     */
    @Override
    public String listMomentForPerson(Map<String, String> params) {
        Integer start = Integer.parseInt(params.get("start"));
        Integer rows = Integer.parseInt(params.get("rows"));
        Integer userId = Integer.parseInt(params.get("userId"));    // 真实的当前登录用户
        Integer viewType = ObjectTool.numberOrNull(params.get("viewType"));
        Integer beViewUserId = ObjectTool.numberOrNull(params.get("beViewUserId"));     // 被查询用户id, 自己查看自己不传
        if(viewType == null || !viewType.equals(CodeTypeConstant.PROFILE_MOMENT_VIEW_TYPE_130) && !viewType.equals(CodeTypeConstant.PROFILE_MOMENT_VIEW_TYPE_131)
                || (userId.intValue() < 1 && beViewUserId == null)){
            return JsonTool.genJson(RetEnum.REQUEST_PARAM_ERROR);   // 请求参数错误
        }
        Integer isSelf = 0;
        if(userId.intValue() > 0 && (beViewUserId == null || beViewUserId.equals(userId))
                && viewType.equals(CodeTypeConstant.PROFILE_MOMENT_VIEW_TYPE_130)){
            /**
             * 点赞作品列表的发布人不一定是自己
             */
            isSelf = 1;
        }

        if(beViewUserId == null){
            beViewUserId = userId;  // 转换查询用户id
        }
        User beViewUser = userCacheDao.selectByPrimaryKey(beViewUserId);
        if(beViewUser == null){ // 查询的用户不存在
            return JsonTool.genJson(RetEnum.USER_VIEW_IS_NOT_EXIST);
        }

        Map<String, Object> momentMap = new HashMap<>();
        momentMap.put("start",start);
        momentMap.put("rows",rows);
        momentMap.put("userId",beViewUserId);
        List<Moment> moments = new ArrayList<>();
        if(viewType.equals(CodeTypeConstant.PROFILE_MOMENT_VIEW_TYPE_130)){  // 作品
            List<Integer> permissionTypes = new ArrayList<>();
            permissionTypes.add(CodeTypeConstant.MOMENT_PERMISSION_TYPE_110);   // 公开

            if(isSelf.intValue() > 0){ // 自己查自己, 公开|好友|私密都会查出来
                permissionTypes.add(CodeTypeConstant.MOMENT_PERMISSION_TYPE_111);   // 好友
                permissionTypes.add(CodeTypeConstant.MOMENT_PERMISSION_TYPE_112);   // 私密
            }else if(userId.intValue() > 0 && !userId.equals(beViewUserId)) {   // 用户登录并且是查看别人
                int isFriend = this.selectIsFriend(userId,beViewUserId);
                if(isFriend > 0) {   // 两个人是好友关系(互相关注)
                    permissionTypes.add(CodeTypeConstant.MOMENT_PERMISSION_TYPE_111);   // 好友
                }
            }
            momentMap.put("permissionTypes", permissionTypes);
            moments = momentDao.selectMomentListForPerson(momentMap);
        }else if(viewType.equals(CodeTypeConstant.PROFILE_MOMENT_VIEW_TYPE_131)){    // 点赞
            List<Integer> permissionTypes = new ArrayList<>();
            /**
             * 点赞, 只查公开类型
             */
            permissionTypes.add(CodeTypeConstant.MOMENT_PERMISSION_TYPE_110);   // 公开
            /*if(userId.intValue() > 0 && !userId.equals(beViewUserId)) {   // 好友
                Map<String, Object> map = new HashMap<>();
                map.put("userId",userId);
                map.put("followerId",beViewUserId);
                List<UserFollow> userFollows = userFollowDao.selectHasFollow(map);
                if(userFollows.size() > 0 && isFollow.intValue() > 0) {   // 两个人是好友关系
                    permissionTypes.add(CodeTypeConstant.MOMENT_PERMISSION_TYPE_111);   // 好友
                }
            }*/
            momentMap.put("permissionTypes", permissionTypes);
            moments = momentDao.selectMomentListForPersonLike(momentMap);     // 暂时只查看公开和好友的作品
        }
        List<Map<String,Object>> momentList = new ArrayList<>();
        // 获取图片alitool
        String OSS_CDN = configCacheDao.selectByCkey(ConfigConstant.OSS_CDN).getCvalue();
        String ACCESS_ID = configCacheDao.selectByCkey(ConfigConstant.ACCESS_ID).getCvalue();
        String ACCESS_KEY = configCacheDao.selectByCkey(ConfigConstant.ACCESS_KEY).getCvalue();
        String BUCKET_ID = configCacheDao.selectByCkey(ConfigConstant.BUCKET_ID).getCvalue();
        // 查看图片用OSS_CDN
        AliTool aliTool = AliTool.getInstance(OSS_CDN, ACCESS_ID, ACCESS_KEY, BUCKET_ID);
        Integer refreshWriteTime = Integer.parseInt(configCacheDao.selectByCkey(ConfigConstant.REFRESH_WRITE_TIME).getCvalue().trim());
        for(Moment moment : moments){
            // 获取视频信息
            Map<String, Object> resultMoment = getMomentVideoInfoMap(userId, refreshWriteTime, moment);

            // 每个视频信息中都要添加
            String nickName = "";
            String provinceName = "";
            String cityName = "";
            String headPortraitUrl = "";// 默认值查看公开的作品
            Integer isFollow = 0;
            if(moment.getPublisher() != null && moment.getPublisher().intValue() > 0){
                Integer publisherId = moment.getPublisher();
                User publisher = userCacheDao.selectByPrimaryKey(publisherId);
                if(publisher.getNickName() != null){
                    nickName = publisher.getNickName();
                }
                if(publisher.getResidenceProvince() != null){    // 获取省市名称
                    provinceName = areaDao.selectByPrimaryKey(publisher.getResidenceProvince()).getName();
                }
                if(publisher.getResidenceCity() != null){
                    cityName = areaDao.selectByPrimaryKey(publisher.getResidenceCity()).getName();
                }
                if(StringUtils.isNotBlank(publisher.getHeadPortraitId())){   // 获取头像地址
                    headPortraitUrl = aliTool.getAccessURL(publisher.getHeadPortraitId());
                }

                // 查询是否关注
                if(userId.intValue() > 0 && !userId.equals(publisherId)){   // 用户登录并且是查看别人
                    Map<String, Object> map = new HashMap<>();
                    map.put("userId",publisherId);
                    map.put("followerId",userId);
                    List<UserFollow> userFollows = userFollowDao.selectHasFollow(map);
                    if(userFollows.size() > 0){ // 有关注关系
                        isFollow = 1;
                    }
                }else if(userId.intValue() > 0 && userId.equals(publisherId)){
                    isFollow = -1;              // 发布人是自己
                }
                /* 发布人信息 */
                resultMoment.put("publisher",publisherId);
                resultMoment.put("nickName",nickName);
                resultMoment.put("provinceName",provinceName);
                resultMoment.put("cityName",cityName);
                resultMoment.put("headPortraitUrl",headPortraitUrl);
                resultMoment.put("isFollow",isFollow);
                momentList.add(resultMoment);
            }
        }
        Map<String, Object> result = new HashMap<>();
        result.put("momentList",momentList);
        return JsonTool.genJson(RetEnum.SUCCESS,result);
    }

    /**
     * 关注动态列表
     * @param params
     * @return
     */
    @Override
    public String listMomentForFollow(Map<String, String> params) {
        Integer start = Integer.parseInt(params.get("start"));
        Integer rows = Integer.parseInt(params.get("rows"));
        Integer userId = Integer.parseInt(params.get("userId"));

        Map<String, Object> map = new HashMap<>();
        map.put("userId",userId);
        map.put("permissionType",CodeTypeConstant.MOMENT_PERMISSION_TYPE_110);  // 只查公开
        map.put("start",start); // 从0开始
        map.put("rows",rows);

        List<Map<String,Object>> momentList = new ArrayList<>();
        Integer refreshWriteTime = Integer.parseInt(configCacheDao.selectByCkey(ConfigConstant.REFRESH_WRITE_TIME).getCvalue().trim());
        // 获取图片alitool
        String OSS_CDN = configCacheDao.selectByCkey(ConfigConstant.OSS_CDN).getCvalue();
        String ACCESS_ID = configCacheDao.selectByCkey(ConfigConstant.ACCESS_ID).getCvalue();
        String ACCESS_KEY = configCacheDao.selectByCkey(ConfigConstant.ACCESS_KEY).getCvalue();
        String BUCKET_ID = configCacheDao.selectByCkey(ConfigConstant.BUCKET_ID).getCvalue();
        // 查看图片用OSS_CDN
        AliTool aliTool = AliTool.getInstance(OSS_CDN, ACCESS_ID, ACCESS_KEY, BUCKET_ID);
        /*查询关注动态列表
        * 查询规则:
        * 1.查询所有关注的用户动态信息
        * 2.只查用户关注当天(包含当天)后的被关注的用户动态, 关注之前的不查
        * 3.查不到结果不处理
        * */
        List<Moment> moments = momentDao.selectMomentListForFollow(map);
        for(Moment moment:moments){
            // 获取视频信息
            Map<String, Object> resultMoment = getMomentVideoInfoMap(userId, refreshWriteTime, moment);

            String nickName = "";
            String provinceName = "";
            String cityName = "";
            String headPortraitUrl = "";
            Integer isFollow = 1;   // 这个默认关注
            if(userId > 0 && userId.equals(moment.getPublisher())){
                isFollow = -1;      // 是自己
            }
            if(moment != null && moment.getPublisher() != null){
                User user = userCacheDao.selectByPrimaryKey(moment.getPublisher());
                if(user.getResidenceProvince() != null){    // 获取省市名称
                    provinceName = areaDao.selectByPrimaryKey(user.getResidenceProvince()).getName();
                }
                if(user.getResidenceCity() != null){
                    cityName = areaDao.selectByPrimaryKey(user.getResidenceCity()).getName();
                }
                if(StringUtils.isNotBlank(user.getHeadPortraitId())){   // 获取头像地址
                    headPortraitUrl = aliTool.getAccessURL(user.getHeadPortraitId());
                }
                nickName = user.getNickName();
            }
            /* 发布人信息 */
            resultMoment.put("publisher",moment.getPublisher());
            resultMoment.put("nickName",nickName);
            resultMoment.put("provinceName",provinceName);
            resultMoment.put("cityName",cityName);
            resultMoment.put("headPortraitUrl",headPortraitUrl);
            resultMoment.put("isFollow",isFollow);
            momentList.add(resultMoment);
        }

        // 查询热推话题, 在banner处显示 只查6条
        List<Map<String,Object>> topicList = new ArrayList<>();
        if(start.intValue() == 0){  // 当第一页的时候才查询banner.后面页数不重复查
            List<Topic> topics = topicDao.selectHotTopicForBanner();
            for (Topic topic : topics){
                Map<String, Object> topicMap = new HashMap<>();
                topicMap.put("name",topic.getName());
                topicMap.put("topId",topic.getId());
                String bannerPicUrl = "";
                if(StringUtils.isNotBlank(topic.getBannerPicId())){ // 热推话题banner图
                    bannerPicUrl = aliTool.getAccessURL(topic.getBannerPicId());
                }
                topicMap.put("bannerPicUrl",bannerPicUrl);
                topicList.add(topicMap);
            }
        }
        Map<String, Object> result = new HashMap<>();
        result.put("momentList",momentList);
        result.put("topicList",topicList);
        return JsonTool.genJson(RetEnum.SUCCESS,result);
    }


    /**
     * 推荐页动态列表
     * @param params
     * @return
     */
    @Override
    public String listMomentForRecommend(Map<String, String> params) {
        Integer rows = Integer.parseInt(params.get("rows"));
        Integer userId = Integer.parseInt(params.get("userId"));

        Map<String, Object> map = new HashMap<>();
        map.put("permissionType",CodeTypeConstant.MOMENT_PERMISSION_TYPE_110);  // 只查公开
        map.put("rows",rows);

        Integer refreshWriteTime = Integer.parseInt(configCacheDao.selectByCkey(ConfigConstant.REFRESH_WRITE_TIME).getCvalue().trim());
        // 获取图片alitool
        String OSS_CDN = configCacheDao.selectByCkey(ConfigConstant.OSS_CDN).getCvalue();
        String ACCESS_ID = configCacheDao.selectByCkey(ConfigConstant.ACCESS_ID).getCvalue();
        String ACCESS_KEY = configCacheDao.selectByCkey(ConfigConstant.ACCESS_KEY).getCvalue();
        String BUCKET_ID = configCacheDao.selectByCkey(ConfigConstant.BUCKET_ID).getCvalue();
        // 查看图片用OSS_CDN
        AliTool aliTool = AliTool.getInstance(OSS_CDN, ACCESS_ID, ACCESS_KEY, BUCKET_ID);
        /**
         * 查询推荐动态列表, 没有分页
         * 1.目前查询规则: 动态库查询随机10条
         * 2.用户登录下, 优先取未观看过的视频, 都看过才取所有视频
         * 3.用户未登录, 取所有视频随机10条
         */
        List<Map<String,Object>> momentList = new ArrayList<>();


        List<Moment> moments = new ArrayList<>();
        if(userId.intValue() > 0){  // 已登录
            map.put("userId",userId);
            moments = momentDao.selectMomentListForRecommendUnPlayed(map);  // 查询未观看过的视频
            if(moments.size() < 1){ // 全都看过了, 取所有视频的随机10条
                map.remove("userId");
                moments = momentDao.selectMomentListForRecommendPlayed(map);
            }
        }else{  // 用户未登录
            moments = momentDao.selectMomentListForRecommendPlayed(map);
        }
        for(Moment moment:moments){
            try{
                Map<String, Object> resultMoment = getMomentVideoInfoMap(userId, refreshWriteTime, moment);
                String nickName = "";
                String provinceName = "";
                String cityName = "";
                String tempHeadPortraitUrl = "";
                Integer isFollow = 0;
                if(userId > 0){     // 用户有登陆, 查询关注关系
                    if(userId.equals(moment.getPublisher())){  // 是自己发布的
                        isFollow = -1;  // 自己发布的,没有+ √
                    }else {
                        // 查询是否关注
                        Map<String, Object> tempMap = new HashMap<>();
                        tempMap.put("userId",moment.getPublisher());
                        tempMap.put("followerId",userId);
                        List<UserFollow> userFollows = userFollowDao.selectHasFollow(tempMap);
                        if(userFollows.size() > 0){ // 有关注关系
                            isFollow = 1;
                        }
                    }
                }
                if(moment != null && moment.getPublisher() != null){
                    User user = userCacheDao.selectByPrimaryKey(moment.getPublisher());
                    if(user == null){   // cache库数据有可能错误
                        LOGGER.info(">>>>>>>>>>>>>>>用户为null,id:{}",moment.getPublisher());
                    }else {
                        if(user.getResidenceProvince() != null){    // 获取省市名称
                            provinceName = areaDao.selectByPrimaryKey(user.getResidenceProvince()).getName();
                        }
                        if(user.getResidenceCity() != null){
                            cityName = areaDao.selectByPrimaryKey(user.getResidenceCity()).getName();
                        }
                        if(StringUtils.isNotBlank(user.getHeadPortraitId())){   // 获取头像地址
                            tempHeadPortraitUrl = aliTool.getAccessURL(user.getHeadPortraitId());
                        }
                        nickName = user.getNickName();
                    }
                }
                /* 发布人信息 */
                resultMoment.put("publisher",moment.getPublisher());
                resultMoment.put("nickName",nickName);
                resultMoment.put("provinceName",provinceName);
                resultMoment.put("cityName",cityName);
                resultMoment.put("headPortraitUrl",tempHeadPortraitUrl);
                resultMoment.put("isFollow",isFollow);
                momentList.add(resultMoment);
            }catch (Exception e){
                LOGGER.error(">>>>>>>>>>>>发生错误,{}",e);
            }
        }
        Map<String, Object> result = new HashMap<>();
        result.put("momentList",momentList);
        return JsonTool.genJson(RetEnum.SUCCESS,result);
    }

    /**
     * 修改动态权限
     * @param params
     * @return
     */
    @Override
    public String updateMomentPermission(Map<String, String> params) {
        Integer userId = Integer.parseInt(params.get("userId"));
        Integer momentId = ObjectTool.numberOrNull(params.get("momentId"));
        Integer permissionType = ObjectTool.numberOrNull(params.get("permissionType"));
        if(permissionType == null || momentId == null 
                || (!permissionType.equals(CodeTypeConstant.MOMENT_PERMISSION_TYPE_110)
                && !permissionType.equals(CodeTypeConstant.MOMENT_PERMISSION_TYPE_111)
                && !permissionType.equals(CodeTypeConstant.MOMENT_PERMISSION_TYPE_112))){
            return JsonTool.genJson(RetEnum.REQUEST_PARAM_ERROR);   // 请求参数错误
        }
        Moment moment = momentCacheDao.selectByPrimaryKey(momentId);
        if(moment == null || moment.getStatus().intValue() == 0){
            return JsonTool.genJson(RetEnum.MOMENT_NOT_EXIST);  // 动态不存在
        }
        if(!moment.getPublisher().equals(userId)){
            return JsonTool.genJson(RetEnum.NO_AUTHORITY_ERROR);    // 无权执行该操作
        }
        moment.setPermissionType(permissionType);
        momentCacheDao.updateByPrimaryKeySelective(moment);
        return JsonTool.genJson(RetEnum.SUCCESS);
    }

    /**
     * 删除动态
     * @param params
     * @return
     */
    @Override
    public String deleteMoment(Map<String, String> params) {
        Integer userId = Integer.parseInt(params.get("userId"));
        Integer momentId = ObjectTool.numberOrNull(params.get("momentId"));
        if(momentId == null){
            return JsonTool.genJson(RetEnum.REQUEST_PARAM_ERROR);   // 请求错误
        }
        Moment moment = momentCacheDao.selectByPrimaryKey(momentId);
        if(moment == null || moment.getStatus().intValue() == 0){
            return JsonTool.genJson(RetEnum.MOMENT_NOT_EXIST);  // 动态不存在
        }
        if(!moment.getPublisher().equals(userId)){
            return JsonTool.genJson(RetEnum.NO_AUTHORITY_ERROR);    // 无权执行该操作
        }
        moment.setStatus(0);
        momentCacheDao.updateByPrimaryKeySelective(moment);
        return JsonTool.genJson(RetEnum.SUCCESS);
    }

    /**
     * 评论动态
     * @param params
     * @return
     */
    @Override
    @Transactional
    public String commentMoment(Map<String, String> params) {
        Integer userId = Integer.parseInt(params.get("userId"));
        Integer momentId = ObjectTool.numberOrNull(params.get("momentId"));
        String commentText = ObjectTool.stringOrNull(params.get("commentText"));
        if(momentId == null || StringUtils.isBlank(commentText) || commentText.length() > 100){
            return JsonTool.genJson(RetEnum.REQUEST_PARAM_ERROR);   // 请求参数错误
        }
        Moment moment = momentCacheDao.selectByPrimaryKey(momentId);
        if(moment == null || moment.getStatus().intValue() == 0){
            return JsonTool.genJson(RetEnum.MOMENT_NOT_EXIST);  // 动态不存在
        }
        if(moment.getPermissionType().equals(CodeTypeConstant.MOMENT_PERMISSION_TYPE_112)){
            return JsonTool.genJson(RetEnum.MOMENT_PRIVATE_DO_NOT_COMMENT);    // 私密作品无法评论
        }
        Integer isPublisher = 0;
        if(moment.getPublisher().equals(userId)){
            isPublisher = 1;     // 是自己的评论,可以删除
        }
        Date now = new Date();
        Comment comment = new Comment();
        comment.setContentText(commentText);
        comment.setMomentId(momentId);
        comment.setSender(userId);
        comment.setStatus(1);   // 状态默认为1:启用
        comment.setCreateTime(now);
        commentDao.insertSelective(comment);

        // 修改redis缓存的统计信息,评论数＋1
        try{
            String momentJson = (String) stringRedisTemplate.opsForHash().get(ConfigConstant.REDIS_MOMENT_HASH_PREFIX, moment.getId() + "");
            if(StringUtils.isNotBlank(momentJson)){
                Map<String, String> redisMomentMap = (Map<String, String>) JSON.parse(momentJson);
                Integer commentCount = Integer.parseInt(redisMomentMap.get(ConfigConstant.REDIS_MOMENT_MAP_KEY_COMMENT_NOW));
                Integer finalCommentCount = new Integer(commentCount.intValue() + 1);
                redisMomentMap.put(ConfigConstant.REDIS_MOMENT_MAP_KEY_COMMENT_NOW,finalCommentCount+"");
                stringRedisTemplate.opsForHash().put(ConfigConstant.REDIS_MOMENT_HASH_PREFIX, moment.getId() + "", JSON.toJSONString(redisMomentMap));
            }
        }catch (Exception e){
            LOGGER.info(">>>>>>>>>>>>>>>>>>修改redis评论数失败,momentId:{}",momentId);
        }

        User user = userCacheDao.selectByPrimaryKey(userId);
        String nickName = user.getNickName();
        // 获取图片alitool
        String OSS_CDN = configCacheDao.selectByCkey(ConfigConstant.OSS_CDN).getCvalue();
        String ACCESS_ID = configCacheDao.selectByCkey(ConfigConstant.ACCESS_ID).getCvalue();
        String ACCESS_KEY = configCacheDao.selectByCkey(ConfigConstant.ACCESS_KEY).getCvalue();
        String BUCKET_ID = configCacheDao.selectByCkey(ConfigConstant.BUCKET_ID).getCvalue();
        // 查看图片用OSS_CDN
        AliTool aliTool = AliTool.getInstance(OSS_CDN, ACCESS_ID, ACCESS_KEY, BUCKET_ID);
        String headPortraitUrl = "";
        if(StringUtils.isNotBlank(user.getHeadPortraitId())){   // 获取头像地址
            headPortraitUrl = aliTool.getAccessURL(user.getHeadPortraitId());
        }

        if(!moment.getPublisher().equals(userId)){   // 是自己评论的, 不添加消息和推送
            // 封装消息内容
            MessageInfoBean bean = new MessageInfoBean();
            bean.setBeOperateObjectId(moment.getId());
            bean.setMessageBody(commentText);
            bean.setVideoId(moment.getVideoId());
            bean.setSenderId(userId);
            bean.setSenderNickName(user.getNickName());
            bean.setMomentId(momentId);
            if(StringUtils.isNotBlank(user.getHeadPortraitId())){
                bean.setSenderHeadPortraitId(user.getHeadPortraitId());
            }
            bean.setCommentId(comment.getId());

            // 添加消息
            Message message = new Message();
            message.setReceiver(moment.getPublisher());
            message.setCreateTime(new Date());
            message.setType(CodeTypeConstant.MESSAGE_CONTENT_TYPE_120); // 评论
            message.setCotnent(JSON.toJSONString(bean));
            messageDao.insertSelective(message);

            // 消息队列发送消息
            Map<String, Object> messageBody = new HashMap<>();
            Map<String, String> fields = new HashMap<>();
            fields.put("nickName",user.getNickName());      // 评论者的昵称
            fields.put("type",CodeTypeConstant.PUSH_MESSAGE_APP_TYPE_1003+"");
            Video video = videoCacheDao.selectByPrimaryKey(moment.getVideoId());
            if(video != null && video.getStatus().intValue() == 1){ // 视频可以播放
                VideoInfoBean videoInfoBean = JSON.parseObject(video.getVideoInfo(), VideoInfoBean.class);
                if(videoInfoBean != null && StringUtils.isNotBlank(videoInfoBean.getCoverUrl())){
                    fields.put("coverUrl",videoInfoBean.getCoverUrl());
                }
            }else {     // 视频不能播放,传id
                fields.put("videoId",moment.getVideoId()+"");
            }
            User publisher = userCacheDao.selectByPrimaryKey(moment.getPublisher());    // 推送给发布者
            messageBody.put("content",ConfigConstant.PUSH_MESSAGE_APP_CONTENT_COMMENT);
            messageBody.put("fields",fields);
            messageBody.put("deviceTokens", publisher.getDeviceToken());
            if(publisher != null &&  StringUtils.isNotBlank(publisher.getDeviceToken())){
                amqpTemplate.convertAndSend(ConfigConstant.MESSAGE_NAME_APP_PUSH_MEASSGE,messageBody);
                LOGGER.info(">>>>>>>>>>>>>>>评论-推送消息发出队列, 参数:{}", messageBody.toString());
            }
        }

        // 封装返回结果
        Map<String, Object> result = new HashMap<>();
        result.put("isPublisher",isPublisher);
        result.put("nickName",nickName);
        result.put("headPortraitUrl",headPortraitUrl);
        result.put("userId",userId);
        result.put("commentId",comment.getId());
        result.put("contentText",commentText);
        result.put("commentTime",now);
        return JsonTool.genJson(RetEnum.SUCCESS,result);
    }

    /**
     * 获取动态的评论列表
     * @param params
     * @return
     */
    @Override
    public String listComment(Map<String, String> params) {
        Integer start = Integer.parseInt(params.get("start"));
        Integer rows = Integer.parseInt(params.get("rows"));
        Integer userId = Integer.parseInt(params.get("userId"));
        Integer momentId = ObjectTool.numberOrNull(params.get("momentId"));
        if(momentId == null){
            return JsonTool.genJson(RetEnum.REQUEST_PARAM_ERROR);
        }
        // 根据momentId查询动态列表
        Map<String, Object> map = new HashMap<>();
        map.put("start",start);
        map.put("rows",rows);
        map.put("momentId",momentId);
        List<Comment> comments = commentDao.selectListCommentByMid(map);

        // 获取ali图片参数配置
        // 获取图片alitool
        String OSS_CDN = configCacheDao.selectByCkey(ConfigConstant.OSS_CDN).getCvalue();
        String ACCESS_ID = configCacheDao.selectByCkey(ConfigConstant.ACCESS_ID).getCvalue();
        String ACCESS_KEY = configCacheDao.selectByCkey(ConfigConstant.ACCESS_KEY).getCvalue();
        String BUCKET_ID = configCacheDao.selectByCkey(ConfigConstant.BUCKET_ID).getCvalue();
        // 查看图片用OSS_CDN
        AliTool aliTool = AliTool.getInstance(OSS_CDN, ACCESS_ID, ACCESS_KEY, BUCKET_ID);

        List<Map<String,Object>> commentList = new ArrayList<>();
        for (Comment comment:comments){
            Map<String, Object> result = new HashMap<>();
            Integer isPublisher = 0;
            Integer sender = null;
            String nickName = "";
            String headPortraitUrl = "";
            String contentText = "";
            Date commentTime = null;
            try {
                if(comment != null && comment.getSender() != null){
                    User user = userCacheDao.selectByPrimaryKey(comment.getSender());
                    if(user != null){
                        sender = user.getId();
                        nickName = user.getNickName();
                        if(user.getId().equals(userId)){
                            isPublisher = 1;    // 是自己的评论
                        }
                        if(StringUtils.isNotBlank(user.getHeadPortraitId())){   // 获取头像地址
                            headPortraitUrl = aliTool.getAccessURL(user.getHeadPortraitId());
                        }
                        contentText = comment.getContentText();
                        commentTime = comment.getCreateTime();
                    }
                }
            }catch (Exception e){
                LOGGER.error(">>>>>>>>>>>获取评论列表出错 请求参数:{} ,错误信息:{}",params.toString(),e);
            }
            result.put("isPublisher",isPublisher);
            result.put("userId",sender);
            result.put("nickName",nickName);
            result.put("headPortraitUrl",headPortraitUrl);
            result.put("contentText",contentText);
            result.put("commentTime",commentTime);
            result.put("commentId",comment.getId());
            commentList.add(result);
        }
        Map<String, Object> result = new HashMap<>();
        result.put("commentList",commentList);
        return JsonTool.genJson(RetEnum.SUCCESS,result);
    }

    /**
     * 删除评论
     * @param params
     * @return
     */
    @Override
    public String deleteComment(Map<String, String> params) {
        Integer userId = Integer.parseInt(params.get("userId"));
        Integer commentId = ObjectTool.numberOrNull(params.get("commentId"));
        if(commentId == null){
            return JsonTool.genJson(RetEnum.REQUEST_PARAM_ERROR);
        }
        Comment comment = commentDao.selectByPrimaryKey(commentId);
        if(comment == null || comment.getStatus().intValue() == 0){ // 0:禁用状态
            return JsonTool.genJson(RetEnum.MOMENT_COMMENT_NOT_EXIST);  // 该评论不存在
        }
        Moment moment = momentCacheDao.selectByPrimaryKey(comment.getMomentId());
        if(moment != null){ // 动态的发布者有权删除该动态下所有评论
            if(moment.getPublisher() != null && !moment.getPublisher().equals(userId)){
                if(!userId.equals(comment.getSender())){    // 检查是否本人操作
                    return JsonTool.genJson(RetEnum.NO_AUTHORITY_ERROR);    // 无权执行该操作
                }
            }
        }
        comment.setStatus(0);
        commentDao.updateByPrimaryKeySelective(comment);

        // redis缓存里评论数量-1
        Integer momentId = comment.getMomentId();
        try{
            String momentJson = (String) stringRedisTemplate.opsForHash().get(ConfigConstant.REDIS_MOMENT_HASH_PREFIX, momentId + "");
            if(StringUtils.isNotBlank(momentJson)){
                Map<String, String> redisMomentMap = (Map<String, String>) JSON.parse(momentJson);
                Integer commentCount = Integer.parseInt(redisMomentMap.get(ConfigConstant.REDIS_MOMENT_MAP_KEY_COMMENT_NOW));
                Integer finalCommentCount = new Integer(commentCount.intValue() - 1);
                if(finalCommentCount.intValue() < 0){
                    finalCommentCount = 0;          // 防止出现负数
                }
                redisMomentMap.put(ConfigConstant.REDIS_MOMENT_MAP_KEY_COMMENT_NOW,finalCommentCount+"");
                stringRedisTemplate.opsForHash().put(ConfigConstant.REDIS_MOMENT_HASH_PREFIX, momentId + "", JSON.toJSONString(redisMomentMap));
            }
        }catch (Exception e){
            LOGGER.info(">>>>>>>>>>>>>>>>>>修改redis评论数失败,momentId:{}",momentId);
        }
        return JsonTool.genJson(RetEnum.SUCCESS);
    }

    /**
     * 点赞动态(视频)
     * @param params
     * @return
     */
    @Override
    public String likeMoment(Map<String, String> params) {
        Integer userId = Integer.parseInt(params.get("userId"));
        Integer momentId = ObjectTool.numberOrNull(params.get("momentId"));
        if(momentId == null){
            return JsonTool.genJson(RetEnum.REQUEST_PARAM_ERROR);
        }
        Moment moment = momentCacheDao.selectByPrimaryKey(momentId);
        if(moment == null || moment.getStatus().intValue() == 0){         // 动态不存在
            return JsonTool.genJson(RetEnum.MOMENT_NOT_EXIST);
        }
        if(moment.getPermissionType().equals(CodeTypeConstant.MOMENT_PERMISSION_TYPE_112)){
            return JsonTool.genJson(RetEnum.MOMENT_PRIVATE_DO_NOT_LIKE);    // 私密作品不要点赞
        }
        Map<String, Object> tempMap = new HashMap<>();
        tempMap.put("userId",userId);
        tempMap.put("momentId",moment.getId());
        List<MomentLike> momentLikes = momentLikeDao.selectMomentHasLiked(tempMap);
        if(momentLikes.size() < 1){ // 没点过赞
            MomentLike momentLike = new MomentLike();
            momentLike.setLikerId(userId);
            momentLike.setMomentId(momentId);
            momentLike.setCreateTime(new Date());
            momentLikeDao.insertSelective(momentLike);  // 新增记录

            // 修改redis缓存的统计信息,点赞数＋1
            try{
                String momentJson = (String) stringRedisTemplate.opsForHash().get(ConfigConstant.REDIS_MOMENT_HASH_PREFIX, momentId + "");
                if(StringUtils.isNotBlank(momentJson)){
                    Map<String, String> redisMomentMap = (Map<String, String>) JSON.parse(momentJson);
                    Integer likeCount = Integer.parseInt(redisMomentMap.get(ConfigConstant.REDIS_MOMENT_MAP_KEY_LIKE_NOW));
                    Integer finalLikeCount = new Integer(likeCount.intValue() + 1);
                    redisMomentMap.put(ConfigConstant.REDIS_MOMENT_MAP_KEY_LIKE_NOW,finalLikeCount+"");
                    stringRedisTemplate.opsForHash().put(ConfigConstant.REDIS_MOMENT_HASH_PREFIX, momentId + "", JSON.toJSONString(redisMomentMap));
                }
            }catch (Exception e){
                LOGGER.info(">>>>>>>>>>>>>>>>>>修改redis点赞数失败,momentId:{},错误信息:{}",momentId,e);
            }

            if(!userId.equals(moment.getPublisher())){   // 是自己的话不发送消息和推送消息
                // 获取图片alitool
                String OSS_CDN = configCacheDao.selectByCkey(ConfigConstant.OSS_CDN).getCvalue();
                String ACCESS_ID = configCacheDao.selectByCkey(ConfigConstant.ACCESS_ID).getCvalue();
                String ACCESS_KEY = configCacheDao.selectByCkey(ConfigConstant.ACCESS_KEY).getCvalue();
                String BUCKET_ID = configCacheDao.selectByCkey(ConfigConstant.BUCKET_ID).getCvalue();
                // 查看图片用OSS_CDN
                AliTool aliTool = AliTool.getInstance(OSS_CDN, ACCESS_ID, ACCESS_KEY, BUCKET_ID);

                // 封装消息内容
                MessageInfoBean bean = new MessageInfoBean();
                bean.setBeOperateObjectId(moment.getId());
                bean.setMessageBody("赞了你的视频");
                bean.setVideoId(moment.getVideoId());
                bean.setSenderId(userId);
                User user = userCacheDao.selectByPrimaryKey(userId);
                bean.setSenderNickName(user.getNickName());
                if(StringUtils.isNotBlank(user.getHeadPortraitId())){
                    bean.setSenderHeadPortraitId(user.getHeadPortraitId());
                }

                // 添加消息
                Message message = new Message();
                message.setReceiver(moment.getPublisher());
                message.setCreateTime(new Date());
                message.setType(CodeTypeConstant.MESSAGE_CONTENT_TYPE_122); // 点赞
                message.setCotnent(JSON.toJSONString(bean));
                messageDao.insertSelective(message);

                // 消息队列发送消息
                Map<String, Object> messageBody = new HashMap<>();
                Map<String, String> fields = new HashMap<>();
                fields.put("nickName",user.getNickName());      // 点赞者的昵称
                fields.put("type",CodeTypeConstant.PUSH_MESSAGE_APP_TYPE_1001+"");
                Video video = videoCacheDao.selectByPrimaryKey(moment.getVideoId());
                if(video != null && video.getStatus().intValue() == 1){ // 视频可以播放
                    VideoInfoBean videoInfoBean = JSON.parseObject(video.getVideoInfo(), VideoInfoBean.class);
                    if(videoInfoBean != null && StringUtils.isNotBlank(videoInfoBean.getCoverUrl())){
                        fields.put("coverUrl",videoInfoBean.getCoverUrl());
                    }
                }else {     // 视频不能播放,传id
                    fields.put("videoId",moment.getVideoId()+"");
                }
                User publisher = userCacheDao.selectByPrimaryKey(moment.getPublisher());    // 推送给发布者
                messageBody.put("content",ConfigConstant.PUSH_MESSAGE_APP_CONTENT_LIKE);
                messageBody.put("fields",fields);
                messageBody.put("deviceTokens", publisher.getDeviceToken());
                if(StringUtils.isNotBlank(publisher.getDeviceToken())){
                    amqpTemplate.convertAndSend(ConfigConstant.MESSAGE_NAME_APP_PUSH_MEASSGE,messageBody);
                    LOGGER.info(">>>>>>>>>>>>>>>点赞-推送消息发出队列, 参数:{}", messageBody.toString());
                }
            }
        }
        return JsonTool.genJson(RetEnum.SUCCESS);
    }

    /**
     * 取消点赞动态(视频)
     * @param params
     * @return
     */
    @Override
    public String deleteMomentLike(Map<String, String> params) {
        Integer userId = Integer.parseInt(params.get("userId"));
        Integer momentId = ObjectTool.numberOrNull(params.get("momentId"));
        if(momentId == null){
            return JsonTool.genJson(RetEnum.REQUEST_PARAM_ERROR);
        }
        Moment moment = momentCacheDao.selectByPrimaryKey(momentId);
        if(moment.getPermissionType().equals(CodeTypeConstant.MOMENT_PERMISSION_TYPE_112)){
            return JsonTool.genJson(RetEnum.MOMENT_IS_PRIVATE);    // 作品已删除
        }
        Map<String, Object> map = new HashMap<>();
        map.put("userId",userId);
        map.put("momentId",momentId);
        momentLikeDao.deleteMomentLikeByParams(map);

        // 修改redis缓存的统计信息,点赞数-1
        try{
            String momentJson = (String) stringRedisTemplate.opsForHash().get(ConfigConstant.REDIS_MOMENT_HASH_PREFIX, momentId + "");
            if(StringUtils.isNotBlank(momentJson)){
                Map<String, String> redisMomentMap = (Map<String, String>) JSON.parse(momentJson);
                Integer likeCount = Integer.parseInt(redisMomentMap.get(ConfigConstant.REDIS_MOMENT_MAP_KEY_LIKE_NOW));
                Integer finalLikeCount = new Integer(likeCount.intValue() - 1);
                if(finalLikeCount.intValue() < 0){  // 防止出现负数
                    finalLikeCount = 0;
                }
                redisMomentMap.put(ConfigConstant.REDIS_MOMENT_MAP_KEY_LIKE_NOW,finalLikeCount+"");
                stringRedisTemplate.opsForHash().put(ConfigConstant.REDIS_MOMENT_HASH_PREFIX, momentId + "", JSON.toJSONString(redisMomentMap));
            }
        }catch (Exception e){
            LOGGER.info(">>>>>>>>>>>>>>>>>>修改redis点赞数失败,momentId:{}",momentId);
        }
        return JsonTool.genJson(RetEnum.SUCCESS);
    }

    /**
     * 分享动态
     * 仅仅是数量加1
     * @param params
     * @return
     */
    @Override
    public String shareMoment(Map<String, String> params) {
        Integer momentId = ObjectTool.numberOrNull(params.get("momentId"));
        if(momentId == null){
            return JsonTool.genJson(RetEnum.REQUEST_PARAM_ERROR);
        }
        Moment moment = momentCacheDao.selectByPrimaryKey(momentId);
        if(moment == null || moment.getStatus().intValue() == 0){         // 动态不存在
            return JsonTool.genJson(RetEnum.MOMENT_NOT_EXIST);
        }
        if(moment.getPermissionType().equals(CodeTypeConstant.MOMENT_PERMISSION_TYPE_112)){
            return JsonTool.genJson(RetEnum.MOMENT_IS_PRIVATE);    // 作品已删除
        }
        // 修改redis缓存的统计信息,分享数+1
        try{
            String momentJson = (String) stringRedisTemplate.opsForHash().get(ConfigConstant.REDIS_MOMENT_HASH_PREFIX, momentId + "");
            if(StringUtils.isNotBlank(momentJson)){
                Map<String, String> redisMomentMap = (Map<String, String>) JSON.parse(momentJson);
                Integer shareCount = Integer.parseInt(redisMomentMap.get(ConfigConstant.REDIS_MOMENT_MAP_KEY_SHARE_NOW));
                Integer finalShareCount = new Integer(shareCount.intValue() + 1);
                redisMomentMap.put(ConfigConstant.REDIS_MOMENT_MAP_KEY_SHARE_NOW,finalShareCount+"");
                stringRedisTemplate.opsForHash().put(ConfigConstant.REDIS_MOMENT_HASH_PREFIX, momentId + "", JSON.toJSONString(redisMomentMap));
            }
        }catch (Exception e){
            LOGGER.info(">>>>>>>>>>>>>>>>>>修改redis点赞数失败,momentId:{}",momentId);
        }
        return JsonTool.genJson(RetEnum.SUCCESS);
    }

    /**
     * 发布动态
     * @param params
     * @return
     */
    @Override
    @Transactional
    public String addMoment(Map<String, String> params) {
        Integer userId = Integer.parseInt(params.get("userId"));
        String contentText = ObjectTool.stringOrNull(params.get("contentText"));
        String textExtra = ObjectTool.stringOrNull(params.get("textExtra"));
        String videoId = ObjectTool.stringOrNull(params.get("videoId"));
        String location = ObjectTool.stringOrNull(params.get("location"));
        String location_name = ObjectTool.stringOrNull(params.get("location_name"));
        String location_address = ObjectTool.stringOrNull(params.get("location_address"));
        Integer permissionType = ObjectTool.numberOrNull(params.get("permissionType"));
        Date madeTime = StringTool.stringToDate(params.get("madeTime"));
        if(videoId == null || permissionType == null
                || (!permissionType.equals(CodeTypeConstant.MOMENT_PERMISSION_TYPE_110)
                && !permissionType.equals(CodeTypeConstant.MOMENT_PERMISSION_TYPE_111)
                && !permissionType.equals(CodeTypeConstant.MOMENT_PERMISSION_TYPE_112))){
            return JsonTool.genJson(RetEnum.REQUEST_PARAM_ERROR);   // 请求参数错误
        }
        Video video = videoDao.selectByVideoId(videoId);
        if(video == null){
            // 首先存储视频
            video = new Video();
            video.setVideoId(videoId);
            video.setMadeTime(madeTime);
            video.setCreateTime(new Date());
            video.setStatus(0);     // 默认为0
            videoCacheDao.insertSelective(video);
        }

        // 存储动态
        Moment moment = new Moment();
        moment.setContentText(contentText);
        moment.setTextExtra(textExtra);
        moment.setVideoId(video.getId());
        moment.setPublisher(userId);
        moment.setPermissionType(permissionType);
        moment.setLocation(location);
        moment.setLocationName(location_name);
        moment.setLocationAddress(location_address);
        moment.setCreateTime(new Date());
        moment.setStatus(1);    // 虽然数据库默认是1, 但redis缓存库没有保存上status,要提前设置
        momentCacheDao.insertSelective(moment);

        if(textExtra != null){  // 有@或话题
            User user = userCacheDao.selectByPrimaryKey(userId);
            // 获取图片alitool
            String OSS_CDN = configCacheDao.selectByCkey(ConfigConstant.OSS_CDN).getCvalue();
            String ACCESS_ID = configCacheDao.selectByCkey(ConfigConstant.ACCESS_ID).getCvalue();
            String ACCESS_KEY = configCacheDao.selectByCkey(ConfigConstant.ACCESS_KEY).getCvalue();
            String BUCKET_ID = configCacheDao.selectByCkey(ConfigConstant.BUCKET_ID).getCvalue();
            // 查看图片用OSS_CDN
            AliTool aliTool = AliTool.getInstance(OSS_CDN, ACCESS_ID, ACCESS_KEY, BUCKET_ID);
            StringBuffer deviceTokens = new StringBuffer();

            List<Map> textExtras = JSONArray.parseArray(textExtra, Map.class);
            for(Map extra : textExtras){
                if(((Integer)extra.get("type")).intValue() == (CodeTypeConstant.MOMENT_TEXT_EXTRA_TYPE_160).intValue()){   // @你
                    Integer remindUserId = (Integer) extra.get("user_id");
                    if(remindUserId != null){
                        try{
                            MomentRemind remind = new MomentRemind();
                            remind.setMomentId(moment.getId());
                            remind.setRemindType(CodeTypeConstant.MOMENT_REMIND_TYPE_101);  // 好友
                            remind.setRemindId(remindUserId);
                            remind.setCreateTime(new Date());
                            momentRemindDao.insertSelective(remind);
                        }catch (Exception e){
                            LOGGER.info(">>>>>>>>>>>>>发布动态--添加remind发生错误 userIds:{} ,错误信息 {}", remindUserId, e);
                        }
                        // 封装消息内容
                        MessageInfoBean bean = new MessageInfoBean();
                        bean.setBeOperateObjectId(moment.getId());
                        bean.setMessageBody(moment.getContentText());
                        String tempTextExtra = StringUtils.isBlank(moment.getTextExtra()) ? "" : moment.getTextExtra();     // 高亮
                        bean.setTextExtra(tempTextExtra);
                        bean.setVideoId(video.getId());
                        bean.setSenderId(userId);
                        bean.setSenderNickName(user.getNickName());
                        bean.setMomentId(moment.getId());
                        if(StringUtils.isNotBlank(user.getHeadPortraitId())){
                            bean.setSenderHeadPortraitId(user.getHeadPortraitId());
                        }
                        // 添加消息
                        Message message = new Message();
                        message.setReceiver(remindUserId);
                        message.setCreateTime(new Date());
                        message.setType(CodeTypeConstant.MESSAGE_CONTENT_TYPE_121); // @你
                        message.setCotnent(JSON.toJSONString(bean));
                        messageDao.insertSelective(message);

                        String deviceToken = "";
                        try{
                            User remindUser = userCacheDao.selectByPrimaryKey(remindUserId);
                            deviceToken = remindUser.getDeviceToken();
                        }catch (Exception e){
                            LOGGER.error(">>>>>>>>>>>>推送消息-获取用户设备token失败: userId,{}, 错误信息:{}", remindUserId, e);
                        }
                        // 推送消息的设备token , 列推
                        if(StringUtils.isNotBlank(deviceToken)){
                            deviceTokens.append(deviceToken).append(",");
                        }
                    }
                }else if(((Integer)extra.get("type")).intValue() == (CodeTypeConstant.MOMENT_TEXT_EXTRA_TYPE_161).intValue()){  // 话题
                    String topicName = (String) extra.get("topic_name");
                    // 查询id,并将话题名称榜上对应id
                    Topic topic = topicDao.selectByTopicNameAccurate(topicName.toLowerCase());
                    if(topic == null){  // 新建话题
                        topic = new Topic();
                        topic.setName(topicName.toLowerCase());
                        topic.setPublisher(userId);
                        topic.setCreateTime(new Date());
                        topicDao.insertSelective(topic);
                    }
                    extra.put("topic_id",topic.getId());    // 回写topicid
                    try{    // 存储动态话题remind
                        MomentRemind remind = new MomentRemind();
                        remind.setMomentId(moment.getId());
                        remind.setRemindType(CodeTypeConstant.MOMENT_REMIND_TYPE_100);  // 话题
                        remind.setRemindId(topic.getId());
                        remind.setCreateTime(new Date());
                        momentRemindDao.insertSelective(remind);
                    }catch (Exception e){
                        LOGGER.info(">>>>>>>>>>>>>发布动态--添加remind发生错误 topids:{} ,错误信息 {}", topic.getId(), e);
                    }
                }
            }
            // textExtras可能因为topic_id的回写发生变化, 要更新moment
            moment.setTextExtra(JSON.toJSONString(textExtras));
            momentCacheDao.updateByPrimaryKeySelective(moment);

            // 推送消息, 因为推送内容一致, 故可以实现列推
            if(deviceTokens.length() > 0){  // 移除最后一个逗号
                String finalDeviceTokens = deviceTokens.substring(0, deviceTokens.length() - 1);
                Map<String, Object> messageBody = new HashMap<>();
                Map<String, String> fields = new HashMap<>();
                fields.put("nickName",user.getNickName());  // 这里是发布者的昵称
                fields.put("type",CodeTypeConstant.PUSH_MESSAGE_APP_TYPE_1002+"");
                fields.put("videoId",video.getId()+"");
                messageBody.put("content",ConfigConstant.PUSH_MESSAGE_APP_CONTENT_REMIND);
                messageBody.put("fields",fields);
                messageBody.put("deviceTokens",finalDeviceTokens);

                /**
                 * 这里发布动态,不能及时推送
                 * 因为ali那边视频转码和回调接口需要时间
                 * 暂时约定延迟30秒
                 */
                amqpTemplate.convertAndSend(ConfigConstant.MESSAGE_NAME_APP_PUSH_MEASSGE, messageBody, new MessagePostProcessor() {
                    @Override
                    public org.springframework.amqp.core.Message postProcessMessage(org.springframework.amqp.core.Message message) throws AmqpException {
                        //设置延迟消费时间30秒
                        message.getMessageProperties().setDelay(ConfigConstant.MESSAGE_DELAY_MS_UPLOAD_VIDEO);
                        return message;
                    }
                });
                LOGGER.info(">>>>>>>>>>>>>>>发布-推送消息发出队列, momentId:{}", moment.getId());
            }
        }
        return JsonTool.genJson(RetEnum.SUCCESS);
    }

    /**
     * 获取视频上传凭证和videoId
     * @param params
     * @return
     */
    @Override
    public String createUploadVideo(Map<String, String> params) {
        LOGGER.info(">>>>>>>>>>>>获取视频上传凭证,参数:{}",params.toString());
        String fileName = ObjectTool.stringOrNull(params.get("fileName"));
        String title = ObjectTool.stringOrNull(params.get("title"));
        if(fileName == null  || title == null){ // 请求参数错误
            return JsonTool.genJson(RetEnum.REQUEST_PARAM_ERROR);
        }
        Map<String, Object> result = AliVideoTool.getInstance(configCacheDao.selectByCkey(ConfigConstant.ACCESSKEYID).getCvalue(),
                configCacheDao.selectByCkey(ConfigConstant.ACCESSKEYSECRET).getCvalue(),
                configCacheDao.selectByCkey(ConfigConstant.ALIVOD_URL).getCvalue(),
                configCacheDao.selectByCkey(ConfigConstant.ALIVOD_PLAY_ACTION).getCvalue()).createUploadVideo(fileName, title);
        return JsonTool.genJson(RetEnum.SUCCESS,result);
    }

    /**
     * 查询动态详情
     * @param params
     * @return
     */
    @Override
    public String singleMoment(Map<String, String> params) {
        Integer userId = Integer.parseInt(params.get("userId"));
        Integer momentId = ObjectTool.numberOrNull(params.get("momentId"));
        if(momentId == null){
            return JsonTool.genJson(RetEnum.REQUEST_PARAM_ERROR);
        }
        Moment moment = momentCacheDao.selectByPrimaryKey(momentId);
        if(moment == null || moment.getStatus().intValue() == 0){
            return JsonTool.genJson(RetEnum.MOMENT_NOT_EXIST);  // 该动态不存在
        }
        // 获取redis刷新数据到数据库的时间配置
//        Integer refreshWriteTime = Integer.parseInt(configCacheDao.selectByCkey(ConfigConstant.REFRESH_WRITE_TIME).getCvalue().trim());
        Integer refreshWriteTime = 300000;
        // 获取图片alitool
        String OSS_CDN = configCacheDao.selectByCkey(ConfigConstant.OSS_CDN).getCvalue();
        String ACCESS_ID = configCacheDao.selectByCkey(ConfigConstant.ACCESS_ID).getCvalue();
        String ACCESS_KEY = configCacheDao.selectByCkey(ConfigConstant.ACCESS_KEY).getCvalue();
        String BUCKET_ID = configCacheDao.selectByCkey(ConfigConstant.BUCKET_ID).getCvalue();
        // 查看图片用OSS_CDN
        AliTool aliTool = AliTool.getInstance(OSS_CDN, ACCESS_ID, ACCESS_KEY, BUCKET_ID);

        Map<String, Object> result = getMomentVideoInfoMap(userId, refreshWriteTime, moment);
        String nickName = "";
        String provinceName = "";
        String cityName = "";
        String tempHeadPortraitUrl = "";
        Integer isFollow = 0;
        if(userId > 0){     // 用户有登陆, 查询关注关系
            if(userId.equals(moment.getPermissionType())){  // 是自己发布的
                isFollow = -1;  // 自己发布的,没有+ √
            }else {
                // 查询是否关注
                Map<String, Object> tempMap = new HashMap<>();
                tempMap.put("userId",moment.getPublisher());
                tempMap.put("followerId",userId);
                List<UserFollow> userFollows = userFollowDao.selectHasFollow(tempMap);
                if(userFollows.size() > 0){ // 有关注关系
                    isFollow = 1;
                }
            }
        }
        if(moment != null && moment.getPublisher() != null){
            User user = userCacheDao.selectByPrimaryKey(moment.getPublisher());
            if(user.getResidenceProvince() != null){    // 获取省市名称
                provinceName = areaDao.selectByPrimaryKey(user.getResidenceProvince()).getName();
            }
            if(user.getResidenceCity() != null){
                cityName = areaDao.selectByPrimaryKey(user.getResidenceCity()).getName();
            }
            if(StringUtils.isNotBlank(user.getHeadPortraitId())){   // 获取头像地址
                tempHeadPortraitUrl = aliTool.getAccessURL(user.getHeadPortraitId());
            }
            nickName = user.getNickName();
        }
            /* 发布人信息 */
        result.put("publisher",moment.getPublisher());
        result.put("nickName",nickName);
        result.put("provinceName",provinceName);
        result.put("cityName",cityName);
        result.put("headPortraitUrl",tempHeadPortraitUrl);
        result.put("isFollow",isFollow);
        return JsonTool.genJson(RetEnum.SUCCESS,result);
    }



    /**
     * 获取动态视频信息
     * @param realUserId
     * @param refreshWriteTime
     * @param moment
     * @return
     */
    private Map<String, Object> getMomentVideoInfoMap(Integer realUserId, Integer refreshWriteTime, Moment moment) {
        Map<String, Object> resultMoment = new HashMap<>();
        Integer likeCount = 0;
        Integer viewCount = 0;
        Integer shareCount = 0;
        Integer commentCount = 0;
        try{
            // 从redis中获取视频统计信息
            String momentJson = (String) stringRedisTemplate.opsForHash().get(ConfigConstant.REDIS_MOMENT_HASH_PREFIX, moment.getId() + "");
            if(StringUtils.isBlank(momentJson)){    // redis中没有该动态信息, 存入
                MomentCount momentCount = momentCountDao.selectByMomentId(moment.getId());
                if(momentCount == null){
                    MomentCount tempMomentCount = new MomentCount();
                    tempMomentCount.setCountComment(0);
                    tempMomentCount.setCountLike(0);
                    tempMomentCount.setCountShare(0);
                    tempMomentCount.setCountView(0);
                    tempMomentCount.setMomentId(moment.getId());
                    tempMomentCount.setPublisher(moment.getPublisher());
                    tempMomentCount.setCreateTime(new Date());
                    momentCountDao.insertSelective(tempMomentCount);
                    momentCount = tempMomentCount;
                }
                // 存入redis
                Map<String, String> redisMomentMap = new HashMap<>();
                redisMomentMap.put(ConfigConstant.REDIS_MOMENT_MAP_KEY_MOMENT,momentCount.getMomentId()+"");
                redisMomentMap.put(ConfigConstant.REDIS_MOMENT_MAP_KEY_LIKE,momentCount.getCountLike()+"");
                redisMomentMap.put(ConfigConstant.REDIS_MOMENT_MAP_KEY_VIEW,momentCount.getCountView()+"");
                redisMomentMap.put(ConfigConstant.REDIS_MOMENT_MAP_KEY_SHARE,momentCount.getCountShare()+"");
                redisMomentMap.put(ConfigConstant.REDIS_MOMENT_MAP_KEY_COMMENT,momentCount.getCountComment()+"");
                redisMomentMap.put(ConfigConstant.REDIS_MOMENT_MAP_KEY_LIKE_NOW,momentCount.getCountLike()+"");
                redisMomentMap.put(ConfigConstant.REDIS_MOMENT_MAP_KEY_VIEW_NOW,momentCount.getCountView()+"");
                redisMomentMap.put(ConfigConstant.REDIS_MOMENT_MAP_KEY_SHARE_NOW,momentCount.getCountShare()+"");
                redisMomentMap.put(ConfigConstant.REDIS_MOMENT_MAP_KEY_COMMENT_NOW,momentCount.getCountComment()+"");
                redisMomentMap.put(ConfigConstant.REDIS_MOMENT_MAP_KEY_WRITE_TIME,new Date().getTime()+"");
                redisMomentMap.put(ConfigConstant.REDIS_MOMENT_MAP_KEY_FLAG,1+"");
                stringRedisTemplate.opsForHash().put(ConfigConstant.REDIS_MOMENT_HASH_PREFIX, moment.getId() + "", JSON.toJSONString(redisMomentMap));

                // 返回结果赋值
                likeCount = momentCount.getCountLike();
                viewCount = momentCount.getCountView();
                shareCount = momentCount.getCountShare();
                commentCount = momentCount.getCountComment();
            }else {
                Map<String, String> redisMomentMap = (Map<String, String>) JSON.parse(momentJson);
                likeCount = Integer.parseInt(redisMomentMap.get(ConfigConstant.REDIS_MOMENT_MAP_KEY_LIKE_NOW));
                viewCount = Integer.parseInt(redisMomentMap.get(ConfigConstant.REDIS_MOMENT_MAP_KEY_VIEW_NOW));
                shareCount = Integer.parseInt(redisMomentMap.get(ConfigConstant.REDIS_MOMENT_MAP_KEY_SHARE_NOW));
                commentCount = Integer.parseInt(redisMomentMap.get(ConfigConstant.REDIS_MOMENT_MAP_KEY_COMMENT_NOW));

                Integer likeCountOld = Integer.parseInt(redisMomentMap.get(ConfigConstant.REDIS_MOMENT_MAP_KEY_LIKE));
                Integer viewCountOld = Integer.parseInt(redisMomentMap.get(ConfigConstant.REDIS_MOMENT_MAP_KEY_VIEW));
                Integer shareCountOld = Integer.parseInt(redisMomentMap.get(ConfigConstant.REDIS_MOMENT_MAP_KEY_SHARE));
                Integer commentCountOld = Integer.parseInt(redisMomentMap.get(ConfigConstant.REDIS_MOMENT_MAP_KEY_COMMENT));
                Integer isFinish = Integer.parseInt(redisMomentMap.get(ConfigConstant.REDIS_MOMENT_MAP_KEY_FLAG));
                Long writeTime = Long.parseLong(redisMomentMap.get(ConfigConstant.REDIS_MOMENT_MAP_KEY_WRITE_TIME));
                long nowTime = new Date().getTime();    // 超过刷新时间才执行
                if(isFinish.intValue() == 1 && ((nowTime - writeTime.longValue()) >= refreshWriteTime)){   // 0:队列存在,等待执行 1:可以发送新的队列
                    if(!likeCount.equals(likeCountOld) || !viewCount.equals(viewCountOld)
                            || !shareCount.equals(shareCountOld) || !commentCount.equals(commentCountOld)){
                        // 数据发生变化,发送队列消息,将新数据写入数据库
                        // 先修改状态位
                        redisMomentMap.put(ConfigConstant.REDIS_MOMENT_MAP_KEY_FLAG,0+"");  // 处理中
                        stringRedisTemplate.opsForHash().put(ConfigConstant.REDIS_MOMENT_HASH_PREFIX, moment.getId() + "", JSON.toJSONString(redisMomentMap));

                        // 修改写入时间
                        redisMomentMap.put(ConfigConstant.REDIS_MOMENT_MAP_KEY_WRITE_TIME,new Date().getTime()+"");
                        amqpTemplate.convertAndSend(ConfigConstant.MESSAGE_NAME_MOMENT_REFRESH_WRITE,redisMomentMap);
                        LOGGER.info(">>>>>>>>>>>>momentRefreshWriteMessage发出消息, 参数:{}",redisMomentMap.toString());
                    }

                }
            }
        }catch (Exception e){
            LOGGER.error(">>>>>>>>>>>>>>从redis中获取视频信息发生错误, momentId {},错误信息  {}",moment.getId(),e);
        }
        // 获取视频信息
        String playUrl = "";
        String coverUrl = "";
        String duration = "0";
        try{
            Integer videoId = moment.getVideoId();
            Video video = videoCacheDao.selectByPrimaryKey(videoId);
            if(video != null){
                String videoInfo = video.getVideoInfo();
                if(video.getStatus().intValue() == 1 && StringUtils.isNotBlank(videoInfo)){  // 有视频信息缓存
                    VideoInfoBean videoInfoBean = JSON.parseObject(videoInfo, VideoInfoBean.class);
                    playUrl = videoInfoBean.getPlayUrl();
                    coverUrl = videoInfoBean.getCoverUrl();
                    duration = videoInfoBean.getDuration();
                }
            }
        }catch (Exception e){
            LOGGER.error(">>>>>>>>>>>>>>发生错误:获取视频信息  {}",e);
        }
        // 查询该用户是否对视频点赞过
        Integer hasLiked = 0;
        if(realUserId.intValue() > 0){  // 用户未登录时id为-1
            Map<String, Object> tempMap = new HashMap<>();
            tempMap.put("userId",realUserId);
            tempMap.put("momentId",moment.getId());
            List<MomentLike> momentLikeList = momentLikeDao.selectMomentHasLiked(tempMap);
            if(momentLikeList.size() > 0){   // 点过赞
                hasLiked = 1;
            }
        }
        /* 动态社交信息 */
        resultMoment.put("viewCount",viewCount);
        resultMoment.put("likeCount",likeCount);
        resultMoment.put("shareCount",shareCount);
        resultMoment.put("commentCount",commentCount);
        resultMoment.put("hasLiked",hasLiked);
        /* 动态视频信息 */
        resultMoment.put("playUrl",playUrl);
        resultMoment.put("coverUrl",coverUrl);
        resultMoment.put("duration",duration);
        /* 动态信息 */
        resultMoment.put("momentId",moment.getId());
        resultMoment.put("contentText",moment.getContentText());
        resultMoment.put("textExtra",moment.getTextExtra());
        resultMoment.put("permissionType",moment.getPermissionType());
        return resultMoment;
    }

    /**
     * 查询是否是朋友
     * @param userId
     * @param beViewUserId
     * @return
     */
    private int selectIsFriend(Integer userId, Integer beViewUserId) {
        Map<String, Object> map = new HashMap<>();
        map.put("userId",userId);
        map.put("followerId",beViewUserId);
        List<UserFollow> userFollows = userFollowDao.selectHasFollow(map);
        map.clear();
        map.put("userId",beViewUserId);
        map.put("followerId",userId);
        List<UserFollow> userFocus = userFollowDao.selectHasFollow(map);
        int isFriend = 0;
        if(userFollows.size() > 0 && userFocus.size() > 0){
            isFriend = 1;
        }
        return isFriend;
    }
}
